home *** CD-ROM | disk | FTP | other *** search
- // ------------------------------- //
- // -------- Start of File -------- //
- // ------------------------------- //
- // ----------------------------------------------------------- //
- // C++ Source Code File Name: btwalker.cpp
- // Compiler Used: MSVC40, DJGPP 2.7.2.1, GCC 2.7.2.1, HP CPP 10.24
- // Produced By: Doug Gaer
- // File Creation Date: 12/02/1998
- // Date Last Modified: 03/15/1999
- // Copyright (c) 1997 Douglas M. Gaer
- // ----------------------------------------------------------- //
- // ------------- Program Description and Details ------------- //
- // ----------------------------------------------------------- //
- /*
- The VBD C++ classes are copyright (c) 1997, by Douglas M. Gaer.
- All those who put this code or its derivatives in a commercial
- product MUST mention this copyright in their documentation for
- users of the products in which this code or its derivative
- classes are used. Otherwise, you have the freedom to redistribute
- verbatim copies of this source code, adapt it to your specific
- needs, or improve the code and release your improvements to the
- public provided that the modified files carry prominent notices
- stating that you changed the files and the date of any change.
-
- THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
- THE ENTIRE RISK OF THE QUALITY AND PERFORMANCE OF THIS SOFTWARE
- IS WITH YOU. SHOULD ANY ELEMENT OF THIS SOFTWARE PROVE DEFECTIVE,
- YOU WILL ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR
- CORRECTION.
-
- The BtreeWalkerb class defines a generic iterator used to walk
- through balanced multi-way file-base trees. The BtreeWalker
- class is a general-purpose class used to sort the entry keys
- and perform search operations.
- */
- // ----------------------------------------------------------- //
- #include "btwalker.h"
- #include "strutil.h"
-
- BtreeWalkerb::BtreeWalkerb(Btree *t, BtreeWalkOrder w)
- : root(*t->GetCache()), curr(*t->GetCache())
- {
- Reset(t, w);
- }
-
- void BtreeWalkerb::Reset(Btree *t, BtreeWalkOrder w)
- {
- // Ensure that the in memory buffers and the file data
- // stay in sync during multiple file access.
- t->TestTree();
-
- tree = t;
- root = t->GetRoot();
- worder = w;
- if (worder == btPREORDER) NextFptr = &BtreeWalkerb::NextPreOrder;
- else if (worder == btINORDER) NextFptr = &BtreeWalkerb::NextInOrder;
- else if (worder == btPOSTORDER) NextFptr = &BtreeWalkerb::NextPostOrder;
- else NextFptr = &BtreeWalkerb::NextLvlOrder;
- state = 0;
- curr = root;
- path.Clear();
- right_path.Clear();
- if ((__LWORD__)root && worder == btLVLORDER) path.Insert((__LWORD__)root);
- }
-
- CachePointer BtreeWalkerb::NextPreOrder()
- // Visit root first, then left, then right subtree
- {
- __LWORD__ addr; // Current address
- CachePointer p(curr); // Parent node pointer
-
- while(1) {
- if((__LWORD__)curr) {
- path.Push((__LWORD__)curr);
- p = curr;
- curr = curr->left;
- return p;
- }
- else if(right_path.Extract(addr) != 0) {
- curr = addr;
- }
- else {
- if(path.Pop(addr) == 0) {
- curr = 0;
- return curr; // No more nodes in the tree
- }
- else {
- p = addr;
- int n = p->cnt;
- for(int i = 0; i < n; i++) {
- if(p->entry[i].right != 0) {
- right_path.Insert((__LWORD__)p->entry[i].right);
- }
- }
- curr = 0; // Travel the right path during the next iteration
- }
- }
- }
- }
-
- CachePointer BtreeWalkerb::NextInOrder()
- // Visit left subtree first, then root, then right
- {
- __LWORD__ addr; // Current address
- CachePointer p(curr); // Parent node pointer
-
- while(1) {
- if((__LWORD__)curr) {
- path.Push((__LWORD__)curr);
- curr = curr->left;
- }
- else if(right_path.Pop(addr) != 0) {
- curr = addr;
- }
- else {
- if(path.Pop(addr) == 0) {
- curr = 0;
- return curr; // No more nodes in the tree
- }
- else {
- p = addr;
- int n = p->cnt;
- for(int i = 0; i < n; i++) {
- if(p->entry[i].right != 0) {
- right_path.Push((__LWORD__)p->entry[i].right);
- }
- }
- curr = 0; // Travel the right path during the next iteration
- return p;
- }
- }
- }
- }
-
- CachePointer BtreeWalkerb::NextLvlOrder()
- // Visit level by level, start at root, and go left to right
- {
- __LWORD__ addr = 0;
- CachePointer p(curr); p = 0;
- if(path.Extract(addr) == 0) return p; else curr = addr;
- int n = curr->cnt;
- if(curr->left != 0) path.Insert((__LWORD__)curr->left);
- for(int i = 0; i < n; i++) {
- if(curr->entry[i].right != 0) path.Insert((__LWORD__)curr->entry[i].right);
- }
- return curr;
- }
-
- CachePointer BtreeWalkerb::NextPostOrder()
- // Visit Left subtree first, then Right, then Root
- {
- __LWORD__ addr, right_addr = 0;
- CachePointer c(curr);
-
- while(1) {
- if(state == 0) { // Ready to go down the tree to left
- if((__LWORD__)curr) {
- path.Push((__LWORD__)curr);
- for(int i = 0; i < curr->cnt; i++) {
- if(curr->entry[i].right != 0) {
- right_path.Push((__LWORD__)curr->entry[i].right);
- }
- }
- curr = curr->left;
- }
- else state = 1;
- }
- else { // State == 1: // Ready to come up the tree
- c = curr;
- if(path.IsEmpty()) {
- curr = 0;
- return curr; // At root
- }
-
- addr = *path.Top();
- curr = addr;
-
- if((__LWORD__)c == curr->left && right_path.Pop(right_addr) != 0) {
- // Coming back up the tree from the left, and
- // there is a right child, so go right.
- // Note that curr is still on top of stack.
- curr = right_addr;
- state = 0;
- }
- else {
- // Coming back up the tree from the right,
- // or there was no right child, so visit
- // the node, and continue on up. (State
- // stays at 1.)
- path.Pop();
- return curr;
- }
- }
- }
- }
-
- int BtreeWalker::Find(const EntryKey &key, EntryKey &e)
- // Finds a specified entry key. Will return true if the key is found
- // or false if the key is not found. The key name, object address,
- // and class ID of the matching entry key will be passed back in
- // entry key "e".
- {
- CachePointer nxt(*btx->GetCache());
- BtreeWalkerb tw(btx, btINORDER);
- nxt = btx->GetRoot();
-
- while((__LWORD__)nxt != 0) {
- nxt = tw.Next();
- if((__LWORD__)nxt) {
- int n = nxt->cnt;
- for(int i = 0; i < n; i++) {
- if(Compare(nxt->entry[i], key) == 0) {
- e = nxt->entry[i];
- return 1;
- }
- }
- }
- }
- return 0;
- }
-
- unsigned BtreeWalker::Sort(EntryKeyVisitFunc Visit)
- // Sorts the entry keys in alphabetical order. The visit action
- // defines a procedure used to process entry keys as they are sorted.
- {
- CachePointer nxt(*btx->GetCache());
- BtreeWalkerb tw(btx, btINORDER);
- int i, j;
- nxt = btx->GetRoot();
- DLList<EntryKey> list; // Short temporary list used to sort keys
- DNode<EntryKey> *ptr;
- DNode<EntryKey> *next_ptr;
-
- unsigned num_objects = 0;
-
- while((__LWORD__)nxt != 0) {
- nxt = tw.Next();
- if((__LWORD__)nxt) {
- if(nxt->left != 0) {
- for(i = 0; i < nxt->cnt; i++) {
- list.StoreNode(nxt->entry[i]);
- }
- continue;
- }
-
- if(!list.IsEmpty()) {
- ptr = list.GetFront();
- for(i = 0, j = 0; i < nxt->cnt; i++) {
- while(!list.IsHeader(ptr)) {
- next_ptr = ptr->GetNext();
- if(FullCompare(ptr->Data, nxt->entry[i].key) < 0) {
- (*Visit)(ptr->Data);
- num_objects++;
- list.Delete(ptr);
- }
- ptr = next_ptr;
- }
- }
- for(; j < nxt->cnt; j++) {
- (*Visit)(nxt->entry[j]);
- num_objects++;
- }
- }
- else {
- for(i = 0; i < nxt->cnt; i++) {
- (*Visit)(nxt->entry[i]);
- num_objects++;
- }
- }
- }
- }
- return num_objects;
- }
-
- unsigned BtreeWalker::Partiallookup(const char *p, EntryKeyVisitFunc Visit)
- // Searches for sub-string pattern "p" in each entry key. The visit action
- // defines a procedure used to process the entry key if a matching sub-string
- // is found. Returns the number of matches found or zero if no matching
- // sub-strings are found.
- {
- CachePointer nxt(*btx->GetCache());
- BtreeWalkerb tw(btx, btINORDER);
- int i, rv, matches = 0;
- nxt = btx->GetRoot();
-
- while((__LWORD__)nxt != 0) {
- nxt = tw.Next();
- if((__LWORD__)nxt) {
- for(i = 0; i < nxt->cnt; i++) {
- rv = FindMatch(nxt->entry[i].key, p);
- if(rv != NOMATCH) {
- (*Visit)(nxt->entry[i]);
- matches++;
- }
- }
- }
- }
- return matches;
- }
- // ----------------------------------------------------------- //
- // ------------------------------- //
- // --------- End of File --------- //
- // ------------------------------- //
-